/**
 * 带有表单域的表格（基于ant-table封装）
 * Created by trj on 2019/6/12
 */
import React, { useEffect, useState } from "react";
import {
  Table,
  Form,
  Input,
  Select,
  Radio,
  Button,
  DatePicker,
  Cascader,
} from "antd";
import _ from "lodash";
import moment from "moment";
import queryString from "querystring";
import InputRange from "./inputRange";
import DateRange from "./dateRange";
import SearchSelect from "../SearchSelect/index.jsx";
import { getUrlSearch } from "../../utils";
import "./index.less";
import { useLocation, useHistory, useParams } from "react-router";
import { useForm } from "antd/es/form/Form";

const FormItem = Form.Item;
const { Option } = Select;
const RadioGroup = Radio.Group;
const RangePicker = DatePicker.RangePicker;
const MonthPicker = DatePicker.MonthPicker;
const EnhancedTable = (props) => {
  const [pagination, setPagination] = useState({
    current: props.dataSource.pageNo || 1,
    pageSize: 15,
    total: props.dataSource.totalCount || 0,
    showTotal(total) {
      return `共 ${total} 条`;
    },
  });
  const location = useLocation();
  const history = useHistory();
  const urlParams = useParams();
  const [form] = useForm();
  const { resetFields, getFieldsValue } = form;
  useEffect(() => {
    props.onSearch({
      ...pagination,
      pageNo: pagination.current,
    });
  }, []);
  // useEffect(()=>{
  //   history.listen(()=>{
  //     console.log("路由变化")
  //     const query = getUrlSearch(location.search);
  //    处理路由变化后的值（分页器处理）
  //      if (query.current && query.pageSize && query.total) {
  //     setPagination(
  //       {
  //         current: query.current,
  //         pageSize: query.pageSize,
  //         total: query.total,
  //         showTotal(total) {
  //           return `共 ${total} 条`;
  //         },
  //       },
  //       () => {
  //         props.onSearch({
  //           ...getFieldsValue(),
  //           ...pagination,
  //           pageNo: pagination.current,
  //         });
  //       }
  //     );
  //   }
  //   })
  // })
  const checkChargePrice = (rule, value, callback) => {
    if (value[0] || value[1]) {
      var regix = /^([\d]+(\.\d{1,2})?$)|^([1-9]+)$/;
      if (
        (value[0] && !regix.test(value[0])) ||
        (value[1] && !regix.test(value[1]))
      ) {
        callback("请正确输入金额且最多保留两位小数");
      } else {
        callback();
      }
    } else {
      callback();
    }
  };

  //包含负数
  const checkChargePriceAll = (rule, value, callback) => {
    if (value[0] || value[1]) {
      var regix = /^([\+ \-]?(([1-9]\d*)|(0)))([.]\d{0,2})?$/;
      if (
        (value[0] && !regix.test(value[0])) ||
        (value[1] && !regix.test(value[1]))
      ) {
        callback("金额最多保留两位小数");
      } else {
        callback();
      }
    } else {
      callback();
    }
  };

  // 动态建立搜索域
  const buildSearchArea = () => {
    const { searchParams } = props;
    const query = urlParams;
    const searchArea = [];

    searchParams.map((item) => {
      switch (item.type) {
        case "input":
          let inputVal = query[item.name] || "";
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={inputVal}
            >
              {item.maxLength ? (
                <Input
                  maxLength={item.maxLength}
                  allowClear
                  placeholder={item.placeholder}
                />
              ) : (
                <Input allowClear placeholder={item.placeholder} />
              )}
            </FormItem>
          );
          break;
        case "select":
          let initialVal = undefined;
          initialVal = query[item.name] || item.initialValue;
          const allowClear = item.allowClear !== false;
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={
                item.name == "staffIds" && initialVal != null
                  ? JSON.parse(initialVal)
                  : initialVal
              }
            >
              {
                <Select
                  mode={item.mode}
                  onChange={(val) => {
                    item.onChange && item.onChange(val, this.props.form);
                  }}
                  showSearch={item.showSearch}
                  filterOption={item.filterOption}
                  style={{ width: item.width || 120 }}
                  placeholder={item.placeholder}
                  allowClear={allowClear}
                >
                  {_.isFunction(item.options)
                    ? item
                        .options()
                        .map((v) => <Option value={v.value}>{v.label}</Option>)
                    : item.options.map((v) => (
                        <Option value={v.value}>{v.label}</Option>
                      ))}
                </Select>
              }
            </FormItem>
          );
          break;
        case "search-select":
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={query[item.name] || item.initialValue}
            >
              {<SearchSelect {...item.searchSelectConfig}></SearchSelect>}
            </FormItem>
          );
          break;
        case "radio":
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={query[item.name] || ""}
            >
              {
                <RadioGroup>
                  {item.options.map((v) => (
                    <Radio value={v.value}>{v.label}</Radio>
                  ))}
                </RadioGroup>
              }
            </FormItem>
          );
          break;
        case "inputRange":
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={
                props.checkChargePrice
                  ? [{ validator: checkChargePriceAll }]
                  : [{ validator: checkChargePrice }]
              }
              initialValue={
                (!_.isEmpty(query[item.name]) &&
                  JSON.parse(query[item.name])) || ["", ""]
              }
            >
              {<InputRange />}
            </FormItem>
          );
          break;
        case "rangepicker":
          const time = (query[item.name] && JSON.parse(query[item.name])) || [];
          const timeStart = time[0] ? moment(time[0]) : null;
          const timeEnd = time[1] ? moment(time[1]) : null;
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={
                query[item.name]
                  ? [timeStart, timeEnd]
                  : item.initialValue || ""
              }
            >
              {
                <RangePicker
                  format="YYYY-MM-DD HH:mm:ss"
                  {..._.omitBy(item, ["title", "name", "type"])}
                />
              }
            </FormItem>
          );
          break;
        case "datepicker":
          const parsedJson =
            (query[item.name] && JSON.parse(query[item.name])) || [];
          const dateStart = parsedJson[0] ? moment(parsedJson[0]) : null;
          const dateEnd = parsedJson[1] ? moment(parsedJson[1]) : null;
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={
                query[item.name]
                  ? [dateStart, dateEnd]
                  : item.initialValue || ""
              }
            >
              {
                <DateRange
                  disabledDateStart={item.disabledDateStart}
                  disabledDateEnd={item.disabledDateEnd}
                />
              }
            </FormItem>
          );
          break;
        case "monthpicker":
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={
                query[item.name]
                  ? moment(JSON.parse(query[item.name]))
                  : item.initialValue || ""
              }
            >
              {<MonthPicker allowClear={item.allowClear} />}
            </FormItem>
          );
          break;
        case "cascader":
          searchArea.push(
            <FormItem
              key={item.title}
              label={item.title}
              name={item.name}
              rules={item.rules || []}
              initialValue={
                (query[item.name] && JSON.parse(query[item.name])) || []
              }
            >
              {
                <Cascader
                  style={{ width: 162 }}
                  options={
                    _.isFunction(item.options) ? item.options() : item.options
                  }
                  placeholder={item.placeholder}
                  changeOnSelect
                />
              }
            </FormItem>
          );
          break;
        case "text":
          searchArea.push(
            <FormItem key={item.title} label={item.title}>
              <span className="ant-form-text">
                {_.isFunction(item.value) ? item.value() : item.value}
              </span>
            </FormItem>
          );
          break;
        default:
          break;
      }
      return item;
    });
    return searchArea;
  };

  /**
   * 格式化url上的查询参数
   * @param params url上的query
   * @return Object
   */
  const formatQueryParams = (params) => {
    const formatParams = _.cloneDeep(params);
    _.mapKeys(formatParams, (value, key) => {
      if (_.isObject(value)) {
        formatParams[key] = JSON.stringify(value);
      }
    });
    return formatParams;
  };

  /**
   * 从url上面剔除form中的参数
   * @param params url参数
   * @param formParams form参数
   * @return Object
   */
  const filterQueryParams = (params, formParams) => {
    const result = {};
    _.mapKeys(params, (value, key) => {
      if (!formParams.hasOwnProperty(key)) {
        result[key] = value;
      }
    });
    return result;
  };
  const onFinishFailed = (errorInfo) => {
    console.log(errorInfo);
  };
  // 表单触发搜索
  const handleSearch = (values) => {
    setPagination({
      ...pagination,
      current: 1,
      pageSize: 15,
    });
    const query = urlParams;
    // 保存查询状态进行路由替换
    const params = {
      ...values,
      ...{ ...pagination, current: 1, pageSize: 15 },
      pageNo: 1,
    };
    history.replace({
      pathname: location.pathname,
      search: queryString.stringify({
        ...formatQueryParams(query),
        ...formatQueryParams(params),
      }),
    });
    props.onSearch(params);
  };
  // 表单重置
  const handleReset = async () => {
    const { onSearch } = props;
    setPagination({
      ...pagination,
      current: 1,
      pageSize: 15,
    });
    // 利用Promise处理异步跳转后的重置
    new Promise((resolve, reject) => {
      resolve(
        history.push({
          pathname: location.pathname,
          search: queryString.stringify({
            ...filterQueryParams(getUrlSearch(location.search), {
              ...getFieldsValue(),
            }),
          }),
        })
      );
    }).then(() => {
      resetFields();
      onSearch({
        ...getFieldsValue(),
        ...{ ...pagination, current: 1, pageSize: 15 },
        pageNo: 1,
      });
    });
  };
  // 表格配置修改（分页器、筛选器等触发搜索）
  const onTableChange = (npagination, filters, sorter) => {
    const { onSearch } = props;
    const changedPagination = { ...pagination, ...npagination };
    setPagination({ ...changedPagination });
    // 保存查询状态进行路由跳转
    const params = {
      ...getFieldsValue(),
      ...changedPagination,
      pageNo: changedPagination.current,
    };
    history.push({
      pathname: location.pathname,
      search: queryString.stringify({
        ...formatQueryParams(location.search),
        ...formatQueryParams(params),
      }),
    });
    onSearch(params);
  };
  // 处理文件导出
  const handleFileExport = () => {
    const { handleExport } = props;
    handleExport({ ...getFieldsValue(), ...pagination });
  };
  const {
    columns,
    dataSource,
    loading,
    hasExport,
    bordered,
    visibleForm = true,
  } = props;
  const searchArea = buildSearchArea();
  return (
    <div className="form-table-box">
      <div className="form-area">
        {visibleForm ? (
          <Form
            form={form}
            layout="inline"
            className="ant-advanced-search-form"
            onFinish={handleSearch}
            onFinishFailed={onFinishFailed}
          >
            {searchArea}
            <span className="btn-area">
              <Button
                style={{ marginRight: 0 }}
                type="primary"
                htmlType="submit"
              >
                查询
              </Button>
              <Button
                style={{ marginLeft: 8, marginRight: 0 }}
                onClick={handleReset}
              >
                重置
              </Button>
              {hasExport && (
                <Button
                  type="primary"
                  style={{ marginLeft: 8 }}
                  onClick={handleFileExport}
                >
                  导出
                </Button>
              )}
            </span>
            {props.children}
          </Form>
        ) : (
          <Form layout="inline" className="ant-advanced-search-form">
            {props.children}
          </Form>
        )}
      </div>
      <div className="table-area">
        <Table
          locale={{ emptyText: "暂无数据" }}
          bordered={bordered}
          columns={columns}
          dataSource={dataSource.result}
          pagination={pagination}
          onChange={onTableChange}
          loading={loading}
          rowClassName={props.rowClassName}
          rowSelection={props.rowSelection}
          rowKey={props.rowKey}
          scroll={props.scroll}
        />
      </div>
    </div>
  );
};

export default EnhancedTable;
